This script runs lme models to test if the soil history affects diverse plant traits

library(tidyverse)
── Attaching packages ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
✔ ggplot2 3.1.0     ✔ purrr   0.2.5
✔ tibble  1.4.2     ✔ dplyr   0.7.8
✔ tidyr   0.8.2     ✔ stringr 1.3.1
✔ readr   1.1.1     ✔ forcats 0.3.0
── Conflicts ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
pheno.all <- readRDS("../Data/pheno_all.RDS")
soil.pal <- c("#92324B","#9e66a7",'#ee5768', '#fdc248', '#1ca04f','#27afb9')
soil.pal.nodav <-  c("#92324B","#9e66a7",'#ee5768', '#fdc248', '#27afb9')

Define the functions

#This function runs a model on all the data
run_lme <- function(df){
  lmerTest::lmer(Value ~ His.Trt + (1|Study/Soil/Tray), data = df)
}
#This function runs a model within each study
run_lme_st <- function(df){
  lmerTest::lmer(Value ~ His.Trt + (1|Soil/Tray), data = df)
}
run_tukey <- function(fit){
  multcomp::glht(fit, linfct = multcomp::mcp(His.Trt = "Tukey")) %>% summary()
}
get_letters <- function(tukey){
  multcomp::cld(tukey, level = 0.05) %>% 
    .$mcletters %>% 
    .$Letters %>% 
    as.data.frame() %>% 
    rename(Letter = ".") %>% 
    mutate(His.Trt = row.names(.))
}
#This function is to define interesting contrasts instead of running all pairwise comparisons a la Tukey
run_contrasts <- function(fit){
  multcomp::glht(fit, 
                 linfct = multcomp::mcp(His.Trt = c(
                   "Naive.Ino - Conditioned.Ino = 0",
                   "Naive.NC - Conditioned.NC = 0",
                   "Naive.NC - Naive.Ino = 0", 
                   "Conditioned.NC - Conditioned.Ino = 0")
                   )
                 ) %>% 
    summary() %>% 
    broom::tidy()
}

I am still not sure what to do about Davis, so I ran analyses both with and without it. I will first focus on the filtered dataset.

pheno.nodav <- filter(pheno.all, Soil != "Davis X")

This chunk looks at the models in which the data from both experiments is included. Since only fresh weight and height were recorded for both, only those two traits are included

by.trait.nodav <- pheno.nodav %>% 
  filter(Trait == "Shoot_fresh_weight" | Trait == "Shoot_length") %>% 
  group_by(Trait) %>% 
  nest
by.trait.nodav <- by.trait.nodav %>% 
  mutate(fit = map(data, run_lme),
         tukey = map(fit, run_tukey),
         letters = map(tukey, get_letters))
by.trait.letters.nodav <- pheno.nodav %>% 
  group_by(History, Trait, Treatment, His.Trt, Inoculum) %>% 
  summarise(Max = max(Value, na.rm = T)) %>% 
  ungroup() %>%
  inner_join(unnest(by.trait.nodav, letters))
Joining, by = c("Trait", "His.Trt")
Column `His.Trt` joining factor and character vector, coercing into character vector
pheno.nodav%>%
  filter(Trait == "Shoot_fresh_weight") %>% 
  ggplot(aes(History, Value)) +
  geom_jitter(aes(shape = paste(Study, Inoculum, sep = " / "), color = Soil),
              alpha = 0.6,
              size = 2) +
  geom_text(data = filter(by.trait.letters.nodav, Trait == "Shoot_fresh_weight"), 
            aes(x = History, y = Max + .1, label = Letter),
            size = 7) +
  ylab("Shoot Fresh Weight (g)") +
  scale_color_manual(values = soil.pal.nodav) +
  scale_shape_manual(values = c(2,17,1,16), name = "Study / Inoculum") +
  facet_grid(. ~ Inoculum, scales = "free") +
  theme_minimal() +
  theme(text = element_text(size = 20))

pheno.nodav%>%
  filter(Trait == "Shoot_length") %>% 
  ggplot(aes(History, Value)) +
  geom_jitter(aes(shape = paste(Study, Inoculum, sep = " / "), color = Soil),
              alpha = 0.6,
              size = 2) +
  geom_text(data = filter(by.trait.letters.nodav, Trait == "Shoot_length"), 
            aes(x = History, y = Max + 2, label = Letter),
            size = 7) +
  ylab("Height (cm)") +
  scale_color_manual(values = soil.pal.nodav) +
  scale_shape_manual(values = c(2,17,1,16), name = "Study / Inoculum") +
  facet_grid(. ~ Inoculum, scales = "free") +
  theme_minimal() +
  theme(text = element_text(size = 20))

Now let’s run the analyses for each expreiment independently.

by.study.trait.nodav <- pheno.nodav%>% 
  group_by(Study,Trait) %>% 
  nest
by.study.trait.nodav <- by.study.trait.nodav %>% 
  mutate(fit = map(data, run_lme_st),
         tukey = map(fit, run_tukey),
         letters = map(tukey, get_letters),
         contrasts = map(fit, run_contrasts))
singular fit
singular fit
singular fit
by.study.trait.letters.nodav <- pheno.nodav%>% 
  group_by(Study,History, Trait, Treatment, His.Trt, Inoculum) %>% 
  summarise(Max = max(Value, na.rm = T)) %>% 
  ungroup() %>%
  inner_join(unnest(by.study.trait.nodav, letters))
Unequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorJoining, by = c("Study", "Trait", "His.Trt")
Column `His.Trt` joining factor and character vector, coercing into character vector
pheno.nodav %>%
  ggplot(aes(History, Value)) +
  geom_jitter(aes(shape = paste(Study, Inoculum, sep = " / "), color = Soil),
              alpha = 0.6,
              size = 2) +
  geom_text(data = by.study.trait.letters.nodav, 
            aes(x = History, y = Max, label = Letter),
            size = 7) +
  scale_color_manual(values = soil.pal.nodav) +
  scale_shape_manual(values = c(2,17,1,16), name = "Study / Inoculum") +
  facet_grid(Study + Trait ~ Inoculum, scales = "free") +
  theme_minimal() +
  theme(text = element_text(size = 20))

When the models are fit within each study, the contrast between conditioned inoculated vs naive mock yields and andjusted p.value greater than 0.05 for the second experiment. I would argue that this contrast is not relevant and we should only focus in the following contrasts: “Naive.Ino - Conditioned.Ino = 0”, “Naive.NC - Conditioned.NC = 0”, “Naive.NC - Naive.Ino = 0”, “Conditioned.NC - Conditioned.Ino = 0”

Here’s what it looks like

by.study.trait.nodav %>% 
  unnest(contrasts) %>% 
  filter(p.value < 0.05) %>% 
  ggplot(aes(lhs, paste(Study, Trait), fill = estimate > 0)) +
  geom_tile() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        text = element_text(size = 15))

This solves the issue for the shoot fresh and dry weight. The root dry weight data is very messy as it was very difficult to collect whole roots for each plant. I suggest removing it.

Now let’s take a look at the models applied to all the data (Davis included) This chunk looks at the models in which the data from both experiments is included.

by.trait <- pheno.all %>% 
  filter(Trait == "Shoot_fresh_weight" | Trait == "Shoot_length") %>% 
  group_by(Trait) %>% 
  nest
by.trait <- by.trait %>% 
  mutate(fit = map(data, run_lme),
         tukey = map(fit, run_tukey),
         letters = map(tukey, get_letters))
by.trait.letters <- pheno.all %>% 
  group_by(History, Trait, Treatment, His.Trt, Inoculum) %>% 
  summarise(Max = max(Value, na.rm = T)) %>% 
  ungroup() %>%
  inner_join(unnest(by.trait, letters))
Unequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorJoining, by = c("Trait", "His.Trt")
Column `His.Trt` joining factor and character vector, coercing into character vector
pheno.all%>%
  filter(Trait == "Shoot_fresh_weight") %>% 
  ggplot(aes(History, Value)) +
  geom_jitter(aes(shape = paste(Study, Inoculum, sep = " / "), color = Soil),
              alpha = 0.6,
              size = 2) +
  geom_text(data = filter(by.trait.letters, Trait == "Shoot_fresh_weight"), 
            aes(x = History, y = Max + .1, label = Letter),
            size = 7) +
  ylab("Shoot Fresh Weight (g)") +
  scale_color_manual(values = soil.pal) +
  scale_shape_manual(values = c(2,17,1,16), name = "Study / Inoculum") +
  facet_grid(. ~ Inoculum, scales = "free") +
  theme_minimal() +
  theme(text = element_text(size = 20))

pheno.all%>%
  filter(Trait == "Shoot_length") %>% 
  ggplot(aes(History, Value)) +
  geom_jitter(aes(shape = paste(Study, Inoculum, sep = " / "), color = Soil),
              alpha = 0.6,
              size = 2) +
  geom_text(data = filter(by.trait.letters, Trait == "Shoot_length"), 
            aes(x = History, y = Max + 2, label = Letter),
            size = 7) +
  ylab("Height (cm)") +
  scale_color_manual(values = soil.pal) +
  scale_shape_manual(values = c(2,17,1,16), name = "Study / Inoculum") +
  facet_grid(. ~ Inoculum, scales = "free") +
  theme_minimal() +
  theme(text = element_text(size = 20))

Now let’s run the analyses for each experiment independently.

by.study.trait <- pheno.all%>% 
  group_by(Study,Trait) %>% 
  nest
by.study.trait <- by.study.trait %>% 
  mutate(fit = map(data, run_lme_st),
         tukey = map(fit, run_tukey),
         letters = map(tukey, get_letters))
singular fit
singular fit
singular fit
by.study.trait.letters <- pheno.all%>% 
  group_by(Study,History, Trait, Treatment, His.Trt, Inoculum) %>% 
  summarise(Max = max(Value, na.rm = T)) %>% 
  ungroup() %>%
  inner_join(unnest(by.study.trait, letters))
Unequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorJoining, by = c("Study", "Trait", "His.Trt")
Column `His.Trt` joining factor and character vector, coercing into character vector
pheno.all %>%
  ggplot(aes(History, Value)) +
  geom_jitter(aes(shape = paste(Study, Inoculum, sep = " / "), color = Soil),
              alpha = 0.6,
              size = 2) +
  geom_text(data = by.study.trait.letters, 
            aes(x = History, y = Max, label = Letter),
            size = 7) +
  scale_color_manual(values = soil.pal) +
  scale_shape_manual(values = c(2,17,1,16), name = "Study / Inoculum") +
  facet_grid(Study + Trait ~ Inoculum, scales = "free") +
  theme_minimal() +
  theme(text = element_text(size = 20))

LS0tCnRpdGxlOiAiUGhlbm8gbW9kZWxzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUaGlzIHNjcmlwdCBydW5zIGxtZSBtb2RlbHMgdG8gdGVzdCBpZiB0aGUgc29pbCBoaXN0b3J5IGFmZmVjdHMgZGl2ZXJzZSBwbGFudCB0cmFpdHMKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKcGhlbm8uYWxsIDwtIHJlYWRSRFMoIi4uL0RhdGEvcGhlbm9fYWxsLlJEUyIpCgpzb2lsLnBhbCA8LSBjKCIjOTIzMjRCIiwiIzllNjZhNyIsJyNlZTU3NjgnLCAnI2ZkYzI0OCcsICcjMWNhMDRmJywnIzI3YWZiOScpCnNvaWwucGFsLm5vZGF2IDwtICBjKCIjOTIzMjRCIiwiIzllNjZhNyIsJyNlZTU3NjgnLCAnI2ZkYzI0OCcsICcjMjdhZmI5JykKYGBgCgpEZWZpbmUgdGhlIGZ1bmN0aW9ucyAKYGBge3J9CgojVGhpcyBmdW5jdGlvbiBydW5zIGEgbW9kZWwgb24gYWxsIHRoZSBkYXRhCnJ1bl9sbWUgPC0gZnVuY3Rpb24oZGYpewogIGxtZXJUZXN0OjpsbWVyKFZhbHVlIH4gSGlzLlRydCArICgxfFN0dWR5L1NvaWwvVHJheSksIGRhdGEgPSBkZikKfQoKI1RoaXMgZnVuY3Rpb24gcnVucyBhIG1vZGVsIHdpdGhpbiBlYWNoIHN0dWR5CnJ1bl9sbWVfc3QgPC0gZnVuY3Rpb24oZGYpewogIGxtZXJUZXN0OjpsbWVyKFZhbHVlIH4gSGlzLlRydCArICgxfFNvaWwvVHJheSksIGRhdGEgPSBkZikKfQoKcnVuX3R1a2V5IDwtIGZ1bmN0aW9uKGZpdCl7CiAgbXVsdGNvbXA6OmdsaHQoZml0LCBsaW5mY3QgPSBtdWx0Y29tcDo6bWNwKEhpcy5UcnQgPSAiVHVrZXkiKSkgJT4lIHN1bW1hcnkoKQp9CgpnZXRfbGV0dGVycyA8LSBmdW5jdGlvbih0dWtleSl7CiAgbXVsdGNvbXA6OmNsZCh0dWtleSwgbGV2ZWwgPSAwLjA1KSAlPiUgCiAgICAuJG1jbGV0dGVycyAlPiUgCiAgICAuJExldHRlcnMgJT4lIAogICAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICAgIHJlbmFtZShMZXR0ZXIgPSAiLiIpICU+JSAKICAgIG11dGF0ZShIaXMuVHJ0ID0gcm93Lm5hbWVzKC4pKQp9CgojVGhpcyBmdW5jdGlvbiBpcyB0byBkZWZpbmUgaW50ZXJlc3RpbmcgY29udHJhc3RzIGluc3RlYWQgb2YgcnVubmluZyBhbGwgcGFpcndpc2UgY29tcGFyaXNvbnMgYSBsYSBUdWtleQpydW5fY29udHJhc3RzIDwtIGZ1bmN0aW9uKGZpdCl7CiAgbXVsdGNvbXA6OmdsaHQoZml0LCAKICAgICAgICAgICAgICAgICBsaW5mY3QgPSBtdWx0Y29tcDo6bWNwKEhpcy5UcnQgPSBjKAogICAgICAgICAgICAgICAgICAgIk5haXZlLklubyAtIENvbmRpdGlvbmVkLklubyA9IDAiLAogICAgICAgICAgICAgICAgICAgIk5haXZlLk5DIC0gQ29uZGl0aW9uZWQuTkMgPSAwIiwKICAgICAgICAgICAgICAgICAgICJOYWl2ZS5OQyAtIE5haXZlLklubyA9IDAiLCAKICAgICAgICAgICAgICAgICAgICJDb25kaXRpb25lZC5OQyAtIENvbmRpdGlvbmVkLklubyA9IDAiKQogICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICkgJT4lIAogICAgc3VtbWFyeSgpICU+JSAKICAgIGJyb29tOjp0aWR5KCkKfQoKYGBgCgpJIGFtIHN0aWxsIG5vdCBzdXJlIHdoYXQgdG8gZG8gYWJvdXQgRGF2aXMsIHNvIEkgcmFuIGFuYWx5c2VzIGJvdGggd2l0aCBhbmQgd2l0aG91dCBpdC4gSSB3aWxsIGZpcnN0IGZvY3VzIG9uIHRoZSBmaWx0ZXJlZCBkYXRhc2V0LiAKYGBge3J9CnBoZW5vLm5vZGF2IDwtIGZpbHRlcihwaGVuby5hbGwsIFNvaWwgIT0gIkRhdmlzIFgiKQpgYGAKCgpUaGlzIGNodW5rIGxvb2tzIGF0IHRoZSBtb2RlbHMgaW4gd2hpY2ggdGhlIGRhdGEgZnJvbSBib3RoIGV4cGVyaW1lbnRzIGlzIGluY2x1ZGVkLiBTaW5jZSBvbmx5IGZyZXNoIHdlaWdodCBhbmQgaGVpZ2h0IHdlcmUgcmVjb3JkZWQgZm9yIGJvdGgsIG9ubHkgdGhvc2UgdHdvIHRyYWl0cyBhcmUgaW5jbHVkZWQKYGBge3J9CmJ5LnRyYWl0Lm5vZGF2IDwtIHBoZW5vLm5vZGF2ICU+JSAKICBmaWx0ZXIoVHJhaXQgPT0gIlNob290X2ZyZXNoX3dlaWdodCIgfCBUcmFpdCA9PSAiU2hvb3RfbGVuZ3RoIikgJT4lIAogIGdyb3VwX2J5KFRyYWl0KSAlPiUgCiAgbmVzdAoKYnkudHJhaXQubm9kYXYgPC0gYnkudHJhaXQubm9kYXYgJT4lIAogIG11dGF0ZShmaXQgPSBtYXAoZGF0YSwgcnVuX2xtZSksCiAgICAgICAgIHR1a2V5ID0gbWFwKGZpdCwgcnVuX3R1a2V5KSwKICAgICAgICAgbGV0dGVycyA9IG1hcCh0dWtleSwgZ2V0X2xldHRlcnMpKQoKYnkudHJhaXQubGV0dGVycy5ub2RhdiA8LSBwaGVuby5ub2RhdiAlPiUgCiAgZ3JvdXBfYnkoSGlzdG9yeSwgVHJhaXQsIFRyZWF0bWVudCwgSGlzLlRydCwgSW5vY3VsdW0pICU+JSAKICBzdW1tYXJpc2UoTWF4ID0gbWF4KFZhbHVlLCBuYS5ybSA9IFQpKSAlPiUgCiAgdW5ncm91cCgpICU+JQogIGlubmVyX2pvaW4odW5uZXN0KGJ5LnRyYWl0Lm5vZGF2LCBsZXR0ZXJzKSkKCnBoZW5vLm5vZGF2JT4lCiAgZmlsdGVyKFRyYWl0ID09ICJTaG9vdF9mcmVzaF93ZWlnaHQiKSAlPiUgCiAgZ2dwbG90KGFlcyhIaXN0b3J5LCBWYWx1ZSkpICsKICBnZW9tX2ppdHRlcihhZXMoc2hhcGUgPSBwYXN0ZShTdHVkeSwgSW5vY3VsdW0sIHNlcCA9ICIgLyAiKSwgY29sb3IgPSBTb2lsKSwKICAgICAgICAgICAgICBhbHBoYSA9IDAuNiwKICAgICAgICAgICAgICBzaXplID0gMikgKwogIGdlb21fdGV4dChkYXRhID0gZmlsdGVyKGJ5LnRyYWl0LmxldHRlcnMubm9kYXYsIFRyYWl0ID09ICJTaG9vdF9mcmVzaF93ZWlnaHQiKSwgCiAgICAgICAgICAgIGFlcyh4ID0gSGlzdG9yeSwgeSA9IE1heCArIC4xLCBsYWJlbCA9IExldHRlciksCiAgICAgICAgICAgIHNpemUgPSA3KSArCiAgeWxhYigiU2hvb3QgRnJlc2ggV2VpZ2h0IChnKSIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc29pbC5wYWwubm9kYXYpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygyLDE3LDEsMTYpLCBuYW1lID0gIlN0dWR5IC8gSW5vY3VsdW0iKSArCiAgZmFjZXRfZ3JpZCguIH4gSW5vY3VsdW0sIHNjYWxlcyA9ICJmcmVlIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApKQoKcGhlbm8ubm9kYXYlPiUKICBmaWx0ZXIoVHJhaXQgPT0gIlNob290X2xlbmd0aCIpICU+JSAKICBnZ3Bsb3QoYWVzKEhpc3RvcnksIFZhbHVlKSkgKwogIGdlb21faml0dGVyKGFlcyhzaGFwZSA9IHBhc3RlKFN0dWR5LCBJbm9jdWx1bSwgc2VwID0gIiAvICIpLCBjb2xvciA9IFNvaWwpLAogICAgICAgICAgICAgIGFscGhhID0gMC42LAogICAgICAgICAgICAgIHNpemUgPSAyKSArCiAgZ2VvbV90ZXh0KGRhdGEgPSBmaWx0ZXIoYnkudHJhaXQubGV0dGVycy5ub2RhdiwgVHJhaXQgPT0gIlNob290X2xlbmd0aCIpLCAKICAgICAgICAgICAgYWVzKHggPSBIaXN0b3J5LCB5ID0gTWF4ICsgMiwgbGFiZWwgPSBMZXR0ZXIpLAogICAgICAgICAgICBzaXplID0gNykgKwogIHlsYWIoIkhlaWdodCAoY20pIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBzb2lsLnBhbC5ub2RhdikgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIsMTcsMSwxNiksIG5hbWUgPSAiU3R1ZHkgLyBJbm9jdWx1bSIpICsKICBmYWNldF9ncmlkKC4gfiBJbm9jdWx1bSwgc2NhbGVzID0gImZyZWUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCkpCmBgYAoKTm93IGxldCdzIHJ1biB0aGUgYW5hbHlzZXMgZm9yIGVhY2ggZXhwcmVpbWVudCBpbmRlcGVuZGVudGx5LgpgYGB7cn0KYnkuc3R1ZHkudHJhaXQubm9kYXYgPC0gcGhlbm8ubm9kYXYlPiUgCiAgZ3JvdXBfYnkoU3R1ZHksVHJhaXQpICU+JSAKICBuZXN0CgpieS5zdHVkeS50cmFpdC5ub2RhdiA8LSBieS5zdHVkeS50cmFpdC5ub2RhdiAlPiUgCiAgbXV0YXRlKGZpdCA9IG1hcChkYXRhLCBydW5fbG1lX3N0KSwKICAgICAgICAgdHVrZXkgPSBtYXAoZml0LCBydW5fdHVrZXkpLAogICAgICAgICBsZXR0ZXJzID0gbWFwKHR1a2V5LCBnZXRfbGV0dGVycyksCiAgICAgICAgIGNvbnRyYXN0cyA9IG1hcChmaXQsIHJ1bl9jb250cmFzdHMpKQoKYnkuc3R1ZHkudHJhaXQubGV0dGVycy5ub2RhdiA8LSBwaGVuby5ub2RhdiU+JSAKICBncm91cF9ieShTdHVkeSxIaXN0b3J5LCBUcmFpdCwgVHJlYXRtZW50LCBIaXMuVHJ0LCBJbm9jdWx1bSkgJT4lIAogIHN1bW1hcmlzZShNYXggPSBtYXgoVmFsdWUsIG5hLnJtID0gVCkpICU+JSAKICB1bmdyb3VwKCkgJT4lCiAgaW5uZXJfam9pbih1bm5lc3QoYnkuc3R1ZHkudHJhaXQubm9kYXYsIGxldHRlcnMpKQoKcGhlbm8ubm9kYXYgJT4lCiAgZ2dwbG90KGFlcyhIaXN0b3J5LCBWYWx1ZSkpICsKICBnZW9tX2ppdHRlcihhZXMoc2hhcGUgPSBwYXN0ZShTdHVkeSwgSW5vY3VsdW0sIHNlcCA9ICIgLyAiKSwgY29sb3IgPSBTb2lsKSwKICAgICAgICAgICAgICBhbHBoYSA9IDAuNiwKICAgICAgICAgICAgICBzaXplID0gMikgKwogIGdlb21fdGV4dChkYXRhID0gYnkuc3R1ZHkudHJhaXQubGV0dGVycy5ub2RhdiwgCiAgICAgICAgICAgIGFlcyh4ID0gSGlzdG9yeSwgeSA9IE1heCwgbGFiZWwgPSBMZXR0ZXIpLAogICAgICAgICAgICBzaXplID0gNykgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBzb2lsLnBhbC5ub2RhdikgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIsMTcsMSwxNiksIG5hbWUgPSAiU3R1ZHkgLyBJbm9jdWx1bSIpICsKICBmYWNldF9ncmlkKFN0dWR5ICsgVHJhaXQgfiBJbm9jdWx1bSwgc2NhbGVzID0gImZyZWUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCkpCgpgYGAKCgpXaGVuIHRoZSBtb2RlbHMgYXJlIGZpdCB3aXRoaW4gZWFjaCBzdHVkeSwgdGhlIGNvbnRyYXN0IGJldHdlZW4gY29uZGl0aW9uZWQgaW5vY3VsYXRlZCB2cyBuYWl2ZSBtb2NrIHlpZWxkcyBhbmQgYW5kanVzdGVkIHAudmFsdWUgZ3JlYXRlciB0aGFuIDAuMDUgZm9yIHRoZSBzZWNvbmQgZXhwZXJpbWVudC4gSSB3b3VsZCBhcmd1ZSB0aGF0IHRoaXMgY29udHJhc3QgaXMgbm90IHJlbGV2YW50IGFuZCB3ZSBzaG91bGQgb25seSBmb2N1cyBpbiB0aGUgZm9sbG93aW5nIGNvbnRyYXN0czoKIk5haXZlLklubyAtIENvbmRpdGlvbmVkLklubyA9IDAiLAoiTmFpdmUuTkMgLSBDb25kaXRpb25lZC5OQyA9IDAiLAoiTmFpdmUuTkMgLSBOYWl2ZS5Jbm8gPSAwIiwKIkNvbmRpdGlvbmVkLk5DIC0gQ29uZGl0aW9uZWQuSW5vID0gMCIKCkhlcmUncyB3aGF0IGl0IGxvb2tzIGxpa2UKYGBge3J9CmJ5LnN0dWR5LnRyYWl0Lm5vZGF2ICU+JSAKICB1bm5lc3QoY29udHJhc3RzKSAlPiUgCiAgZmlsdGVyKHAudmFsdWUgPCAwLjA1KSAlPiUgCiAgZ2dwbG90KGFlcyhsaHMsIHBhc3RlKFN0dWR5LCBUcmFpdCksIGZpbGwgPSBlc3RpbWF0ZSA+IDApKSArCiAgZ2VvbV90aWxlKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKQpgYGAKVGhpcyBzb2x2ZXMgdGhlIGlzc3VlIGZvciB0aGUgIHNob290IGZyZXNoIGFuZCBkcnkgd2VpZ2h0LiBUaGUgcm9vdCBkcnkgd2VpZ2h0IGRhdGEgaXMgdmVyeSBtZXNzeSBhcyBpdCB3YXMgdmVyeSBkaWZmaWN1bHQgdG8gY29sbGVjdCB3aG9sZSByb290cyBmb3IgZWFjaCBwbGFudC4gSSBzdWdnZXN0IHJlbW92aW5nIGl0LiAgCgpOb3cgbGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIG1vZGVscyBhcHBsaWVkIHRvIGFsbCB0aGUgZGF0YSAoRGF2aXMgaW5jbHVkZWQpClRoaXMgY2h1bmsgbG9va3MgYXQgdGhlIG1vZGVscyBpbiB3aGljaCB0aGUgZGF0YSBmcm9tIGJvdGggZXhwZXJpbWVudHMgaXMgaW5jbHVkZWQuCmBgYHtyfQpieS50cmFpdCA8LSBwaGVuby5hbGwgJT4lIAogIGZpbHRlcihUcmFpdCA9PSAiU2hvb3RfZnJlc2hfd2VpZ2h0IiB8IFRyYWl0ID09ICJTaG9vdF9sZW5ndGgiKSAlPiUgCiAgZ3JvdXBfYnkoVHJhaXQpICU+JSAKICBuZXN0CgpieS50cmFpdCA8LSBieS50cmFpdCAlPiUgCiAgbXV0YXRlKGZpdCA9IG1hcChkYXRhLCBydW5fbG1lKSwKICAgICAgICAgdHVrZXkgPSBtYXAoZml0LCBydW5fdHVrZXkpLAogICAgICAgICBsZXR0ZXJzID0gbWFwKHR1a2V5LCBnZXRfbGV0dGVycykpCgpieS50cmFpdC5sZXR0ZXJzIDwtIHBoZW5vLmFsbCAlPiUgCiAgZ3JvdXBfYnkoSGlzdG9yeSwgVHJhaXQsIFRyZWF0bWVudCwgSGlzLlRydCwgSW5vY3VsdW0pICU+JSAKICBzdW1tYXJpc2UoTWF4ID0gbWF4KFZhbHVlLCBuYS5ybSA9IFQpKSAlPiUgCiAgdW5ncm91cCgpICU+JQogIGlubmVyX2pvaW4odW5uZXN0KGJ5LnRyYWl0LCBsZXR0ZXJzKSkKCnBoZW5vLmFsbCU+JQogIGZpbHRlcihUcmFpdCA9PSAiU2hvb3RfZnJlc2hfd2VpZ2h0IikgJT4lIAogIGdncGxvdChhZXMoSGlzdG9yeSwgVmFsdWUpKSArCiAgZ2VvbV9qaXR0ZXIoYWVzKHNoYXBlID0gcGFzdGUoU3R1ZHksIElub2N1bHVtLCBzZXAgPSAiIC8gIiksIGNvbG9yID0gU29pbCksCiAgICAgICAgICAgICAgYWxwaGEgPSAwLjYsCiAgICAgICAgICAgICAgc2l6ZSA9IDIpICsKICBnZW9tX3RleHQoZGF0YSA9IGZpbHRlcihieS50cmFpdC5sZXR0ZXJzLCBUcmFpdCA9PSAiU2hvb3RfZnJlc2hfd2VpZ2h0IiksIAogICAgICAgICAgICBhZXMoeCA9IEhpc3RvcnksIHkgPSBNYXggKyAuMSwgbGFiZWwgPSBMZXR0ZXIpLAogICAgICAgICAgICBzaXplID0gNykgKwogIHlsYWIoIlNob290IEZyZXNoIFdlaWdodCAoZykiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHNvaWwucGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMiwxNywxLDE2KSwgbmFtZSA9ICJTdHVkeSAvIElub2N1bHVtIikgKwogIGZhY2V0X2dyaWQoLiB+IElub2N1bHVtLCBzY2FsZXMgPSAiZnJlZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSkKCnBoZW5vLmFsbCU+JQogIGZpbHRlcihUcmFpdCA9PSAiU2hvb3RfbGVuZ3RoIikgJT4lIAogIGdncGxvdChhZXMoSGlzdG9yeSwgVmFsdWUpKSArCiAgZ2VvbV9qaXR0ZXIoYWVzKHNoYXBlID0gcGFzdGUoU3R1ZHksIElub2N1bHVtLCBzZXAgPSAiIC8gIiksIGNvbG9yID0gU29pbCksCiAgICAgICAgICAgICAgYWxwaGEgPSAwLjYsCiAgICAgICAgICAgICAgc2l6ZSA9IDIpICsKICBnZW9tX3RleHQoZGF0YSA9IGZpbHRlcihieS50cmFpdC5sZXR0ZXJzLCBUcmFpdCA9PSAiU2hvb3RfbGVuZ3RoIiksIAogICAgICAgICAgICBhZXMoeCA9IEhpc3RvcnksIHkgPSBNYXggKyAyLCBsYWJlbCA9IExldHRlciksCiAgICAgICAgICAgIHNpemUgPSA3KSArCiAgeWxhYigiSGVpZ2h0IChjbSkiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHNvaWwucGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMiwxNywxLDE2KSwgbmFtZSA9ICJTdHVkeSAvIElub2N1bHVtIikgKwogIGZhY2V0X2dyaWQoLiB+IElub2N1bHVtLCBzY2FsZXMgPSAiZnJlZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSkKCmBgYAoKTm93IGxldCdzIHJ1biB0aGUgYW5hbHlzZXMgZm9yIGVhY2ggZXhwZXJpbWVudCBpbmRlcGVuZGVudGx5LgpgYGB7cn0KYnkuc3R1ZHkudHJhaXQgPC0gcGhlbm8uYWxsJT4lIAogIGdyb3VwX2J5KFN0dWR5LFRyYWl0KSAlPiUgCiAgbmVzdAoKYnkuc3R1ZHkudHJhaXQgPC0gYnkuc3R1ZHkudHJhaXQgJT4lIAogIG11dGF0ZShmaXQgPSBtYXAoZGF0YSwgcnVuX2xtZV9zdCksCiAgICAgICAgIHR1a2V5ID0gbWFwKGZpdCwgcnVuX3R1a2V5KSwKICAgICAgICAgbGV0dGVycyA9IG1hcCh0dWtleSwgZ2V0X2xldHRlcnMpKQoKYnkuc3R1ZHkudHJhaXQubGV0dGVycyA8LSBwaGVuby5hbGwlPiUgCiAgZ3JvdXBfYnkoU3R1ZHksSGlzdG9yeSwgVHJhaXQsIFRyZWF0bWVudCwgSGlzLlRydCwgSW5vY3VsdW0pICU+JSAKICBzdW1tYXJpc2UoTWF4ID0gbWF4KFZhbHVlLCBuYS5ybSA9IFQpKSAlPiUgCiAgdW5ncm91cCgpICU+JQogIGlubmVyX2pvaW4odW5uZXN0KGJ5LnN0dWR5LnRyYWl0LCBsZXR0ZXJzKSkKCnBoZW5vLmFsbCAlPiUKICBnZ3Bsb3QoYWVzKEhpc3RvcnksIFZhbHVlKSkgKwogIGdlb21faml0dGVyKGFlcyhzaGFwZSA9IHBhc3RlKFN0dWR5LCBJbm9jdWx1bSwgc2VwID0gIiAvICIpLCBjb2xvciA9IFNvaWwpLAogICAgICAgICAgICAgIGFscGhhID0gMC42LAogICAgICAgICAgICAgIHNpemUgPSAyKSArCiAgZ2VvbV90ZXh0KGRhdGEgPSBieS5zdHVkeS50cmFpdC5sZXR0ZXJzLCAKICAgICAgICAgICAgYWVzKHggPSBIaXN0b3J5LCB5ID0gTWF4LCBsYWJlbCA9IExldHRlciksCiAgICAgICAgICAgIHNpemUgPSA3KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHNvaWwucGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMiwxNywxLDE2KSwgbmFtZSA9ICJTdHVkeSAvIElub2N1bHVtIikgKwogIGZhY2V0X2dyaWQoU3R1ZHkgKyBUcmFpdCB+IElub2N1bHVtLCBzY2FsZXMgPSAiZnJlZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSkKYGBgCg==